/**
 * WebSocket 客户端
 * 处理与服务器的 WebSocket 连接和消息通信
 */

class WebSocketClient extends EventTarget {
  constructor() {
    super();
    
    this.ws = null;
    this.clientId = null;
    this.connectionState = 'disconnected'; // disconnected, connecting, connected, error
    this.reconnectAttempts = 0;
    this.reconnectTimer = null;
    this.heartbeatTimer = null;
    this.messageQueue = []; // 离线消息队列
    this.rateLimitTracker = new Map();
    
    // 绑定方法
    this.connect = this.connect.bind(this);
    this.disconnect = this.disconnect.bind(this);
    this.send = this.send.bind(this);
    this.onOpen = this.onOpen.bind(this);
    this.onMessage = this.onMessage.bind(this);
    this.onError = this.onError.bind(this);
    this.onClose = this.onClose.bind(this);
  }
  
  /**
   * 连接到 WebSocket 服务器
   */
  connect() {
    if (this.connectionState === 'connecting' || this.connectionState === 'connected') {
      Utils.error.log('WebSocket 已连接或正在连接');
      return;
    }
    
    this.connectionState = 'connecting';
    this.emit('connecting');
    
    try {
      const url = CONFIG.websocket.getUrl();
      Utils.error.log(`正在连接 WebSocket: ${url}`, 'WebSocketClient');
      
      this.ws = new WebSocket(url);
      this.ws.addEventListener('open', this.onOpen);
      this.ws.addEventListener('message', this.onMessage);
      this.ws.addEventListener('error', this.onError);
      this.ws.addEventListener('close', this.onClose);
      
    } catch (error) {
      Utils.error.log('创建 WebSocket 连接失败', 'WebSocketClient');
      this.handleConnectionError(error);
    }
  }
  
  /**
   * 断开 WebSocket 连接
   */
  disconnect(reason = 'manual') {
    this.clearTimers();
    
    if (this.ws) {
      this.ws.removeEventListener('open', this.onOpen);
      this.ws.removeEventListener('message', this.onMessage);
      this.ws.removeEventListener('error', this.onError);
      this.ws.removeEventListener('close', this.onClose);
      
      if (this.ws.readyState === WebSocket.OPEN) {
        this.ws.close(1000, reason);
      }
      
      this.ws = null;
    }
    
    this.connectionState = 'disconnected';
    this.clientId = null;
    this.emit('disconnected', { reason });
  }
  
  /**
   * 发送消息
   */
  send(type, content, options = {}) {
    const message = {
      type,
      content,
      messageId: Utils.generateId(),
      timestamp: new Date().toISOString(),
      ...options
    };
    
    // 检查连接状态
    if (this.connectionState !== 'connected') {
      Utils.error.log('WebSocket 未连接，消息已加入队列', 'WebSocketClient');
      this.messageQueue.push(message);
      return false;
    }
    
    // 检查速率限制
    if (!this.checkRateLimit()) {
      Utils.error.notify('消息发送过于频繁，请稍后再试');
      return false;
    }
    
    try {
      this.ws.send(JSON.stringify(message));
      Utils.error.log(`发送消息: ${type}`, 'WebSocketClient');
      return true;
    } catch (error) {
      Utils.error.log('发送消息失败', 'WebSocketClient');
      Utils.error.notify('发送消息失败，请检查网络连接');
      return false;
    }
  }
  
  /**
   * WebSocket 连接打开事件
   */
  onOpen(event) {
    Utils.error.log('WebSocket 连接已建立', 'WebSocketClient');
    
    this.connectionState = 'connected';
    this.reconnectAttempts = 0;
    
    // 开始心跳检测
    this.startHeartbeat();
    
    // 发送队列中的消息
    this.processMessageQueue();
    
    this.emit('connected');
  }
  
  /**
   * WebSocket 消息接收事件
   */
  onMessage(event) {
    try {
      const message = JSON.parse(event.data);
      Utils.error.log(`收到消息: ${message.type}`, 'WebSocketClient');
      
      // 处理特殊消息类型
      switch (message.type) {
        case 'connection':
          this.handleConnectionMessage(message);
          break;
          
        case 'pong':
          this.handlePongMessage(message);
          break;
          
        case 'error':
          this.handleErrorMessage(message);
          break;
          
        default:
          this.emit('message', message);
          break;
      }
      
    } catch (error) {
      Utils.error.log('解析消息失败', 'WebSocketClient');
    }
  }
  
  /**
   * WebSocket 错误事件
   */
  onError(event) {
    Utils.error.log('WebSocket 连接错误', 'WebSocketClient');
    this.handleConnectionError(event);
  }
  
  /**
   * WebSocket 关闭事件
   */
  onClose(event) {
    Utils.error.log(`WebSocket 连接已关闭: ${event.code} - ${event.reason}`, 'WebSocketClient');
    
    this.clearTimers();
    this.connectionState = 'disconnected';
    this.clientId = null;
    
    this.emit('disconnected', {
      code: event.code,
      reason: event.reason,
      wasClean: event.wasClean
    });
    
    // 如果不是手动关闭，尝试重连
    if (event.code !== 1000 && CONFIG.websocket.reconnect.enabled) {
      this.scheduleReconnect();
    }
  }
  
  /**
   * 处理连接消息
   */
  handleConnectionMessage(message) {
    if (message.content && message.content.success) {
      this.clientId = message.content.clientId;
      Utils.error.log(`获得客户端 ID: ${this.clientId}`, 'WebSocketClient');
    }
  }
  
  /**
   * 处理 pong 消息
   */
  handlePongMessage(message) {
    Utils.error.log('收到 pong 响应', 'WebSocketClient');
    // pong 响应表明连接正常
  }
  
  /**
   * 处理错误消息
   */
  handleErrorMessage(message) {
    const { code, message: errorMsg, details } = message.content || {};
    Utils.error.log(`服务器错误: ${code} - ${errorMsg}`, 'WebSocketClient');
    
    // 根据错误类型处理
    switch (code) {
      case 'RATE_LIMIT':
        Utils.error.notify('消息发送过于频繁，请稍后再试');
        break;
        
      case 'INVALID_FORMAT':
      case 'INVALID_CONTENT':
        Utils.error.notify('消息格式错误');
        break;
        
      case 'NOT_JOINED':
        Utils.error.notify('请先加入聊天室');
        break;
        
      default:
        Utils.error.notify(errorMsg || '服务器错误');
        break;
    }
    
    this.emit('error', { code, message: errorMsg, details });
  }
  
  /**
   * 处理连接错误
   */
  handleConnectionError(error) {
    this.connectionState = 'error';
    this.emit('error', error);
    
    if (CONFIG.websocket.reconnect.enabled) {
      this.scheduleReconnect();
    }
  }
  
  /**
   * 安排重连
   */
  scheduleReconnect() {
    const config = CONFIG.websocket.reconnect;
    
    if (this.reconnectAttempts >= config.maxAttempts) {
      Utils.error.log('达到最大重连次数，停止重连', 'WebSocketClient');
      this.emit('reconnectFailed');
      return;
    }
    
    this.reconnectAttempts++;
    
    // 计算延迟时间（指数退避）
    const delay = Math.min(
      config.delay * Math.pow(config.backoffFactor, this.reconnectAttempts - 1),
      config.maxDelay
    );
    
    Utils.error.log(`${delay}ms 后尝试第 ${this.reconnectAttempts} 次重连`, 'WebSocketClient');
    
    this.emit('reconnectScheduled', { 
      attempt: this.reconnectAttempts, 
      delay,
      maxAttempts: config.maxAttempts
    });
    
    this.reconnectTimer = setTimeout(() => {
      this.connect();
    }, delay);
  }
  
  /**
   * 开始心跳检测
   */
  startHeartbeat() {
    if (!CONFIG.websocket.heartbeat.enabled) return;
    
    this.heartbeatTimer = setInterval(() => {
      if (this.connectionState === 'connected') {
        this.send('ping', { timestamp: Date.now() });
      }
    }, CONFIG.websocket.heartbeat.interval);
  }
  
  /**
   * 清理定时器
   */
  clearTimers() {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
    
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }
  
  /**
   * 处理消息队列
   */
  processMessageQueue() {
    while (this.messageQueue.length > 0 && this.connectionState === 'connected') {
      const message = this.messageQueue.shift();
      try {
        this.ws.send(JSON.stringify(message));
      } catch (error) {
        Utils.error.log('发送队列消息失败', 'WebSocketClient');
        break;
      }
    }
  }
  
  /**
   * 检查速率限制
   */
  checkRateLimit() {
    if (!CONFIG.security.rateLimit.enabled) return true;
    
    const { maxMessages, timeWindow } = CONFIG.security.rateLimit;
    return Utils.rateLimiter.check('websocket_send', maxMessages, timeWindow);
  }
  
  /**
   * 发送事件
   */
  emit(eventType, data = null) {
    const event = new CustomEvent(eventType, { detail: data });
    this.dispatchEvent(event);
    
    if (CONFIG.debug.enabled) {
      Utils.error.log(`事件: ${eventType}`, 'WebSocketClient');
    }
  }
  
  /**
   * 获取连接状态
   */
  getConnectionState() {
    return {
      state: this.connectionState,
      clientId: this.clientId,
      reconnectAttempts: this.reconnectAttempts,
      queuedMessages: this.messageQueue.length,
      wsReadyState: this.ws ? this.ws.readyState : null
    };
  }
  
  /**
   * 获取连接统计
   */
  getStats() {
    return {
      connectionState: this.connectionState,
      clientId: this.clientId,
      reconnectAttempts: this.reconnectAttempts,
      queuedMessages: this.messageQueue.length,
      isOnline: Utils.network.isOnline(),
      wsUrl: CONFIG.websocket.getUrl()
    };
  }
}